﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Platform.Storage.Redis.Messages
{
	public class SubscribeMessage : RedisMessageBase<Subscription>
	{

		internal SubscribeMessage( RedisMessageChannel communication, SubscriptionMatch match, string[] channels )
			: base(
				communication,
				( match == SubscriptionMatch.ByPattern? "PSUBSCRIBE" : "SUBSCRIBE" ),
				channels )
		{ }

		protected override Subscription GetReply( Func<RedisReplyLine> nextLine )
		{
			// Retorna a quantidade que estao ativos
			var header = nextLine();

			Trace.Assert( header.Reply == RedisReplyStatus.Collection );

			int collectionCount = Convert.ToInt32( header.Message );
			List<string> channels = new List<string>( collectionCount - 1 );
			while ( collectionCount-- > 1 )
			{
				var channelLine = nextLine();
				Trace.Assert( channelLine.Reply == RedisReplyStatus.CollectionItem );
				if ( !this.IgnoreLine( channelLine ) )
					channels.Add( channelLine.Message );
			}

			var subscriptionsLine = nextLine();
			Trace.Assert( subscriptionsLine.Reply == RedisReplyStatus.Number );
			return new Subscription( Convert.ToInt32( subscriptionsLine.Message ), channels );
		}

		/// <summary>
		/// Ignora a mensagem retornada pelo REDIS informando que foi enviado um comando
		/// subscribe
		/// </summary>
		/// <param name="line"></param>
		/// <returns></returns>
		private bool IgnoreLine( RedisReplyLine line )
		{
			return line.Reply == RedisReplyStatus.CollectionItem
				&& this.Command.Equals( line.Message, StringComparison.InvariantCultureIgnoreCase );
		}

	}


	public class Subscription
	{
		internal Subscription( int count, IEnumerable<string> channels )
		{
			this.MonitoringCount = count;
			this.Channels = channels;
		}

		public IEnumerable<string> Channels
		{ get; private set; }

		public int MonitoringCount
		{ get; private set; } 
	}

}
